package me.yh.tech.dynamic;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import me.yh.tech.dynamic.service.impl.ServiceImplLW;
import me.yh.tech.util.JavaForm;
import me.yh.tech.util.compiler.JavaStringCompiler;

/**
 * 在静态代码(应用)中定义接口, 动态生成的代码去实现接口(推荐) 动态对象就可以强转为该接口类型, 并调用其相关方法
 *
 * @author liwei
 *
 */
public class App4 {

	public static String LOCAL_PATH="E:\\CompilerTest";//E:\\CompilerTest /opt/temp/
	public static String LOCAL_NAME="ServiceImpl03.java";

	public static final String SOURCE_CODE = 
			"package tech.ldxy.dynamic.service.impl;"
			/* "" */
			+ "import java.util.ArrayList;"
			+ "import java.util.List;"
			+ "import java.util.HashMap;"
			+ "import java.util.Map;"
			+ "import com.alibaba.fastjson.JSONObject;" 
			+ "public class ServiceImpl03 {"
			+ "private List list = new ArrayList();"
			+ "public static void start(String name) {"
			+ "Map<String, String> map = new HashMap<>();"
			+ "map.put(\"1\",\"v\");"
			+ "JSONObject.toJSONString(map);" 
			+ "System.out.println(\"--- start server ---\"+name);" + "}"
			+ "public void stop() {"
			+ "System.out.println(\"--- end server ---\");" + "}"
			+ "}";

	public static void main(String[] args) throws Exception {
		System.out.println("操作系统名称："+System.getProperty("os.name"));
		System.out.println("操作系统架构："+System.getProperty("os.arch"));
		System.out.println("操作系统版本："+System.getProperty("os.version"));
		//	动态加载第三方jar

		// 文件输出到本地
		writeOcrStrtoFile(JavaForm.formJava(SOURCE_CODE), LOCAL_PATH, LOCAL_NAME);
		// 读取本地文件,执行 java 文件
		wreadOcrStrtoFile(LOCAL_PATH, LOCAL_NAME);
		
		System.out.println(System.getProperty("java.class.path"));
		System.out.println(System.getProperty("java.library.path"));
		System.out.println(System.getProperty("java.ext.dirs"));
		System.out.println(System.getProperty("path.separator"));

	}

	/**
	 * 保存文件到本地
	 * 
	 * @param result
	 * @param outPath
	 * @param outFileName
	 * @throws Exception
	 */
	public static void writeOcrStrtoFile(String result, String outPath, String outFileName) throws Exception {
		File dir = new File(outPath);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		File txt = new File(outPath + "/" + outFileName);
		if (!txt.exists()) {
			txt.createNewFile();
		}
		byte bytes[] = new byte[512];
		bytes = result.getBytes();
		int b = bytes.length; // 是字节的长度，不是字符串的长度
		FileOutputStream fos = new FileOutputStream(txt);
//		fos.write(bytes, 0, b);
		fos.write(bytes);
		fos.flush();
		fos.close();
		System.out.println("写入成功："+txt);
	}

	/**
	 * 读取本地文件
	 *
	 * @param outPath
	 * @param outFileName
	 * @throws Exception
	 */
	public static void wreadOcrStrtoFile(String outPath, String outFileName) throws Exception {
		String path = outPath + "/" + outFileName;
		JavaStringCompiler compiler = new JavaStringCompiler(); // 创建动态编译器
		// 读取本地的java文件
		StringBuffer buffer = new StringBuffer();
		BufferedReader bf = new BufferedReader(new FileReader(path));
		String s = null;
		while ((s = bf.readLine()) != null) {// 使用readLine方法，一次读一行
			//buffer.append(s.trim());
			buffer.append(s.trim());
		}

		String xml = buffer.toString();
		// 关闭流
		bf.close();
		System.out.println("读取到的文件内容:"+xml);

		//设置编译参数
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//设置class的文件的查找目录 即引用对象的地址
		//JAR_PATH + "\\lombok.jar" "D:/growup/dynamic-load/external/jar/lombok.jar"
		String lombokPath = "E:\\git\\dynamic-load\\external\\jar\\lombok.jar";
		String fastjsonPath = "E:\\git\\dynamic-load\\external\\jar\\fastjson.jar";
		ops.add("-classpath");
		ops.add(lombokPath + File.pathSeparatorChar + fastjsonPath);
		
		// 动态加载 classload 自定义
		//ClassLoadTest.loadClasspath();
		//System.setProperty("java.class.path", System.getProperty("java.class.path")+ File.pathSeparatorChar+lombokPath + File.pathSeparatorChar + fastjsonPath);
		try {
			// 动态编译 Java 文件, 生成字节码  不使用jar
			//Map<String, byte[]> result = compiler.compile("ServiceImpl03.java", xml);
			//提前加载jar
			Map<String, byte[]> result = compiler.compile("ServiceImpl03.java", xml,ops);
			Class<?> clazz = compiler.loadClass("tech.ldxy.dynamic.service.impl.ServiceImpl03", result);
			Object obj = clazz.newInstance();  // 使用反射创建对象
			
			clazz.getMethod("start",String.class).invoke(obj,"liwei");  // 调用 ServiceImpl2 有参的 start 方法
        	//clazz.getMethod("start").invoke(obj,new Object[] {"liwei"});  // 调用 ServiceImpl2 无参的 start 方法
        	clazz.getMethod("stop").invoke(obj);  // 调用 ServiceImpl2 无参的 stop 方法
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}
	
}
